/* 
*  Copyright (C) 2009-2010 WCG Project
*
*  This program is free software; you can redistribute it and/or modify it
*  under the terms of the GNU General Public License as published by the
*  Free Software Foundation; either version 2 of the License, or (at
*  your option) any later version.
*
*  This program is distributed in the hope that it will be useful, but
*  WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
*  General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software Foundation,
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*  In addition, as a special exception, the author gives permission to
*  link the code of this program with the Half-Life Game Engine ("HL
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
*  respects for all of the code used other than the HL Engine and MODs
*  from Valve. If you modify this file, you may extend this exception
*  to your version of the file, but you are not obligated to do so. If
*  you do not wish to do so, delete this exception statement from your
*  version.
*/


/*
*  WarCraft Generations for AMX Mod X (http://wcg.googlecode.com)
*
*  Based on Warcraft 3 Frozen Throne by Geesu, Avanderik & YamiKaitou.
*
*  http://www.war3ft.com
*
*/



#pragma dynamic			65536
//#pragma tabsize		0
//#pragma semicolon		1

new const PLUGIN_NAME[]		=	"Warcraft Generations"
new const PLUGIN_AUTHOR[]	=	"Wizzie (aka Kaktus)"
new const PLUGIN_VERSION[]	=	"Beta 7"
new const PLUGIN_DATE[]		=	__DATE__

// Let AMX X know that we NEED these modules (as of amx x 1.75)
#pragma reqclass	xstats
#pragma reqlib		fakemeta
#pragma reqlib		cstrike
#pragma loadlib		sqlite
#pragma loadlib		mysql

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <fakemeta>
#include <fakemeta_util>
#include <hamsandwich>
#include <dbi>
#include <sqlx>

// Header files that contain function declarations and variables
#include "wcg/defines.inc"
#include "wcg/variables.inc"
#include "wcg/db/db_common.inc"
#include "wcg/db/db_mysqlx.inc"
#include "wcg/db/db_sqlite.inc"
#include "wcg/stocks.inl"
#include "wcg/effects.inl"
#include "wcg/cvar.inl"
#include "wcg/cstrike.inl"
#include "wcg/classes/global.inl"
#include "wcg/classes/rogue.inl"
#include "wcg/classes/paladin.inl"
#include "wcg/classes/shaman.inl"
#include "wcg/classes/druid.inl"
#include "wcg/classes/warlock.inl"
#include "wcg/classes/hunter.inl"
#include "wcg/classes/priest.inl"
#include "wcg/classes/mage.inl"
#include "wcg/forwards.inl"
#include "wcg/XP.inl"
#include "wcg/db/db_mysqlx.inl"
#include "wcg/db/db_sqlite.inl"
#include "wcg/db/db_common.inl"
#include "wcg/war3ft.inl"
#include "wcg/events.inl"
#include "wcg/clientCommands.inl"
#include "wcg/items.inl"
#include "wcg/shared.inl"
#include "wcg/player.inl"
#include "wcg/menus.inl"
#include "wcg/motd.inl"
#include "wcg/language.inl"
#include "wcg/admin.inl"
#include "wcg/statusicons.inl"
#include "wcg/util.inl"
#include "wcg/attributes.inl"
#include "wcg/skill_manager.inl"


//-----------------------------------------
// plugin_init
//
//-----------------------------------------
public plugin_init()
{
	register_plugin( PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR )
	
	if ( is_running( "cstrike" ) )
		GameInfo[GI_Mod] = GAME_CSTRIKE
	else if ( is_running( "czero" ) )
		GameInfo[GI_Mod] = GAME_CZERO

	gmsgDeathMsg		= get_user_msgid( "DeathMsg"	)
	gmsgScreenFade		= get_user_msgid( "ScreenFade"	)
	gmsgScreenShake		= get_user_msgid( "ScreenShake"	)
	gmsgScoreInfo		= get_user_msgid( "ScoreInfo"	)
	gmsgBarTime			= get_user_msgid( "BarTime" 	)
	gmsgStatusText		= get_user_msgid( "StatusText" 	)
	gmsgStatusIcon		= get_user_msgid( "StatusIcon" 	)
	gmsgSayText			= get_user_msgid( "SayText" 	)
	gmsgTextMsg			= get_user_msgid( "TextMsg" 	)

	g_HUDSync_StatusText = CreateHudSyncObj()

	register_dictionary( "wcg.txt")

	register_concmd( "playerskills", "CMD_Handler", -1 )
	register_concmd( "wcg_givexp", "ADMIN_Handler", -1, " -- Gives XP to players" )
	register_concmd( "wcg_setlevel", "ADMIN_Handler", -1, " -- Sets a player's level" )
	register_concmd( "wcg_giveitem", "ADMIN_Handler", -1, " -- Gives an item to a player" )

	register_clcmd( "wcgmenu",		"CMD_Handler", -1 )
	register_clcmd( "wcghelp",		"CMD_Handler", -1 )

	register_clcmd( "levitation",	"CMD_Handler", -1 )
	register_clcmd( "changeclass",	"CMD_Handler", -1 )
	register_clcmd( "selectskill",	"CMD_Handler", -1 )
	register_clcmd( "selectattrib",	"CMD_Handler", -1 )
	register_clcmd( "skillsinfo",	"CMD_Handler", -1 )
	register_clcmd( "attribsinfo",	"CMD_Handler", -1 )
	register_clcmd( "resetskills",	"CMD_Handler", -1 )
	register_clcmd( "resetxp",		"CMD_Handler", -1 )
	register_clcmd( "itemsinfo",	"CMD_Handler", -1 )
	register_clcmd( "itemsinfo2",	"CMD_Handler", -1 )
	register_clcmd( "shopmenu",		"CMD_Handler", -1 )
	register_clcmd( "shopmenu2",	"CMD_Handler", -1 )
	register_clcmd( "ankh",			"CMD_Handler", -1 )
	register_clcmd( "amulet",		"CMD_Handler", -1 )
	register_clcmd( "boots",		"CMD_Handler", -1 )
	register_clcmd( "claws",		"CMD_Handler", -1 )
//	register_clcmd( "cloak",		"CMD_Handler", -1 )
//	register_clcmd( "chameleon",	"CMD_Handler", -1 )
	register_clcmd( "frost",		"CMD_Handler", -1 )
	register_clcmd( "gloves",		"CMD_Handler", -1 )
	register_clcmd( "health",		"CMD_Handler", -1 )
//	register_clcmd( "helm",			"CMD_Handler", -1 )
	register_clcmd( "mask",			"CMD_Handler", -1 )
	register_clcmd( "necklace",		"CMD_Handler", -1 )
	register_clcmd( "rings",		"CMD_Handler", -1 )
	register_clcmd( "socks",		"CMD_Handler", -1 )
//	register_clcmd( "scroll",		"CMD_Handler", -1 )
	register_clcmd( "tome",			"CMD_Handler", -1 )
	register_clcmd( "level",		"CMD_Handler", -1 )
	register_clcmd( "ability",		"cmd_Ability", -1 )
	register_clcmd( "ultimate",		"cmd_Ultimate", -1 )
	register_clcmd( "fullupdate",	"cmd_fullupdate", -1 )
	register_clcmd( "drop",			"cmd_Drop", -1 )
	register_clcmd( "jointeam",		"cmd_Jointeam", -1 )
	register_clcmd( "say",			"cmd_Say", -1 )
	register_clcmd( "say_team",		"cmd_Say", -1 )
	register_clcmd( "hegren",		"cmd_hegren" )


	// legacy cmds
	register_clcmd( "war3menu",		"CMD_Handler", -1 )
	register_clcmd( "war3help",		"CMD_Handler", -1 )
	register_clcmd( "changerace",	"CMD_Handler", -1 )




	register_menucmd( register_menuid( "BuyItem" ), (1<<3), "cmd_hegren" )		// Old Style
	register_menucmd( -34, (1<<3), "cmd_hegren" )								// VGUI

	// Old style menu (now its jointeam client command)
	register_menucmd( register_menuid( "Team_Select", 1 ), (1<<0)|(1<<1)|(1<<4), "cmd_Teamselect" )


	// Format mod name
	formatex( GameInfo[GI_ModName], 31, "%s %s", PLUGIN_NAME, PLUGIN_VERSION )


	// Plugin initialization procedures
	WC3_Init()

//	register_concmd( "test", "test" )
}


//-----------------------------------------
// test
//
//-----------------------------------------
public test(id)
{
//	new param[4]
//	param[0] = 2
//	param[1] = id
//	_SPELL_Entangle( param )

//	new param[2]
//	param[0] = id
//	param[1] = 10
//	PLAYER_CastSpell( id, ABILITY_CHAINHEAL, CAST_NORMAL, "_SPELL_ChainHeal", param, 2, CAST_IGNORE_COOLDOWN|CAST_IGNORE_MANA_COST )


//	new param[2]
//	param[0] = 2
//	param[1] = 5
//	PLAYER_CastSpell( 2, ULTIMATE_STEALTH, CAST_NORMAL, "_SPELL_Stealth", param, 2, CAST_SKIP_ENDCAST_SOUND | CAST_IGNORE_COOLDOWN )

//	new param[2]
//	param[0] = 2
//	param[1] = id
//	PLAYER_CastSpell( id, SKILL_HOJ, CAST_PASSIVE, "_SPELL_HoJ", param, 2 )
	

//	new param[2]
//	param[0] = 2
//	param[1] = id
//	set_task( 0.0, "_SPELL_Immolate", _, param, 2 )

//	new param[1]
//	param[0] = id
//	set_task( 0.0, "_SPELL_Blink", _, param, 1 )


//	new param[3]
//	param[0] = id
//	param[1] = 2
//	param[2] = 5
//	set_task( 0.0, "_SPELL_Frostbolt", _, param, 3 )

//	new param[3]
//	param[0] = 2
//	param[1] = id
//	set_task( 0.0, "_SPELL_BlastWave", _, param, 3 )

//	new param[1]
//	param[0] = id
//	set_task( 0.0, "_SPELL_BindingHeal", _, param, 1 )

//	new param[2]
//	param[0] = 2
//	param[1] = id
//	PLAYER_CastSpell( 2, SKILL_SMITE, CAST_PASSIVE, "_SPELL_Smite", param, 2 )

//	new param[2]
//	param[0] = 2
//	param[1] = id
//	PLAYER_CastSpell( 2, SKILL_ARCANESHOT, CAST_PASSIVE, "_SPELL_ArcaneShot", param, 2 )

//	new param[2]
//	param[0] = 2
//	param[1] = id
//	PLAYER_CastSpell( 2, SKILL_SERPENTSTING, CAST_PASSIVE, "_SPELL_SerpentSting", param, 2 )



//	new iVictim = id
//	if( !PlayerInfo[iVictim][PI_IsPolymorphed] )
//	{
//		new param[2]
//		param[0] = id
//		param[1] = iVictim
//		set_task( 0.0, "_SPELL_PolyChicken", _, param, 2 )
//	}
//	else
//		_RemovePolyChicken( iVictim )
	


/*
	new param[5]
	param[0] = id
	param[1] = 2
	param[2] = HIT_HEAD
	param[3] = 5
	param[4] = 50
	PLAYER_CastSpell( 2, SKILL_THORNS, CAST_PASSIVE, "_SPELL_ThornsAura", param, 5, CAST_IGNORE_MANA_COST )
*/

//	new param[1]
//	param[0] = 2
//	PLAYER_CastSpell( 2, ULTIMATE_LOCUSTSWARM, CAST_NORMAL, "_SPELL_LocustSwarm", param, 1, CAST_IGNORE_COOLDOWN|CAST_IGNORE_MANA_COST )


//	new param[1]
//	param[0] = 2
//	PLAYER_CastSpell( 2, ULTIMATE_SUICIDE, CAST_NORMAL, "_SPELL_Suicide", param, 1, CAST_IGNORE_PLANT_DEFUSE )


//	EFFECT_ScreenFade( id, 0.25, 0.1, COLOR_RGBA(0, 255, 0, 30) )

//	PLAYER_Damage( 0.0, id, id, 30, CSW_USP, HIT_CHEST, DMG_GENERIC )

//	PLAYER_CheckMagicHit( 1, 2 )
//	PlayerInfo[id][PI_RespawnBy] = RESPAWN_SOULSTONE
//	PLAYER_Spawn( 1 )


//	new param[2]
//	param[0] = 2
//	set_task( 0.0, "_SPELL_BeastWithin", _, param, 1 )

}


//-----------------------------------------
// plugin_end
//
//-----------------------------------------
public plugin_end()
{
	remove_task( TASK_GLOBAL_HEARTBEAT )

	static szCurMap[32]
	get_mapname( szCurMap, 31 )
	WC3_Log( false, "** Map '%s' ended", szCurMap )

	DB_SaveAll( false )
	DB_Prune()
	DB_Close()
	return
}



//-----------------------------------------
// plugin_precache
//
//-----------------------------------------
public plugin_precache()
{
	WCG_Precache()
}



//-----------------------------------------
// client_putinserver
//
//-----------------------------------------
public client_putinserver( id )
{
	// Check for steam ID pending
	static szPlayerID[32]
	
	get_user_authid( id, szPlayerID, 31 )
	
	// Then the player doesn't have a steam id, lets make them reconnect
	if( equal(szPlayerID, "STEAM_ID_PENDING") )
	{
		client_cmd( id, "reconnect" )
		return
	}

	// Get the user's ID!
	DB_FetchUniqueID( id )

	// Check user's cvar if the user isn't a bot and if we're not running a 64-bit server
//	if ( !is_user_bot( id ) && !is_amd64_server() )
//		query_client_cvar( id, "cl_minmodels", "_CS_CheckMinModelsValue" )

	if ( GameInfo[GI_Mod] == GAME_CZERO )
	{
		// Only want to run this if: mod is CZ (zbot not supported), client is a bot,
		// these are CZ bots (bot_quota), and the ham has not been registed yet.
		if ( (pev(id, pev_flags) & FL_FAKECLIENT) && get_pcvar_num(CVAR_bot_quota) > 0 )
			set_task( 0.1, "CZ_BotHookHam", id ) // Delay for private data to initialize
	}

	return
}



//-----------------------------------------
// client_infochanged
//
//-----------------------------------------
public client_infochanged( id )
{
	get_user_name( id, PlayerInfo[id][PI_PlayerOldName], 31 )
	get_user_info( id, "name", PlayerInfo[id][PI_PlayerName], 31 )
	return PLUGIN_CONTINUE
}




//-----------------------------------------
// client_connect
//
//-----------------------------------------
public client_connect( id )
{
	get_user_name( id, PlayerInfo[id][PI_PlayerName], 31 )
	get_user_name( id, PlayerInfo[id][PI_PlayerOldName], 31 )

	// Initialize this player
	WCG_ResetPlayerInfo( id )

	client_cmd( id, "hud_centerid 0" )

	client_cmd(id, "echo ")
	client_cmd(id, "echo ^" *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=* ^" ")
	client_cmd(id, "echo ^" *=-=                                            ^" ")
	client_cmd(id, "echo ^" *=-=      Welcome to Warcraft Generations       ^" ")
	client_cmd(id, "echo ^" *=-=     based on Warcraft 3 Frozen Throne      ^" ")
	client_cmd(id, "echo ^" *=-=                                            ^" ")
	client_cmd(id, "echo ^" *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=* ^" ")
	client_cmd(id, "echo ") 

	return PLUGIN_CONTINUE
}



//-----------------------------------------
// client_disconnect
//
//-----------------------------------------
public client_disconnect( id )
{
	// Update the user's timestamps for each race if we're saving XP
	DB_UpdateTimestamp( id )

	// Save the user's XP if we have XP to save
	if( !is_user_bot(id) && PlayerInfo[id][PI_Class] && PlayerInfo[id][PI_XP] )
		DB_SaveXP( id, false )

	WCG_ResetPlayerInfo( id )
	WCG_SortTeams(id)
}




//-----------------------------------------
// plugin_natives
//
//-----------------------------------------
public plugin_natives()
{
	set_module_filter( "module_filter" )
	set_native_filter( "native_filter" )
	set_error_filter( "error_filter" )
}



//-----------------------------------------
// error_filter
//
//-----------------------------------------
public error_filter( error_code, bool:debugging, message[] ) 
{
	static szBuffer[256]
	dbg_fmt_error( szBuffer, 255 )
	log_amx( "[ERROR] '%s' '%d' '%d' '%s'", message, error_code, debugging, szBuffer )

	//L 12/27/2006 - 16:48:08: [wcg.amxx] [ERROR] '[CSTRIKE] Invalid player 5' '10' '1' 'Run time error 10: native error (native "cs_set_user_money")'
}


//-----------------------------------------
// module_filter
//
//-----------------------------------------
public module_filter( const module[] )
{
	if ( equal( module, "dbi" ) || equal( module, "sqlx" ) )
		return PLUGIN_HANDLED

	// Dammit plugin can't load now :/ - technically we should never get here unless the module doesn't exist in the modules folder
	else
	{
		WC3_Log( true, "Please enable the '%s' module in your modules.ini file", module )
		return PLUGIN_CONTINUE
	}
	return PLUGIN_HANDLED
}



//-----------------------------------------
// native_filter
//
//-----------------------------------------
public native_filter( const name[], index, trap )
{
	if ( !trap )
		return PLUGIN_HANDLED

	return PLUGIN_CONTINUE
}
